﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using Csla.Data;
using System.Data;
using System.Data.Common;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;

namespace Asah.SiteWorx.ProductCatalog
{
    [Serializable()]
    public class ProductList : Csla.ReadOnlyListBase<ProductList, ProductInfo>
    {

        # region Factory Methods

        public static ProductList GetProductList()
        {
            return DataPortal.Fetch<ProductList>();
        }

        public static ProductList GetProductList(int catalogId)
        {
            return DataPortal.Fetch<ProductList>(new CatalogCriteria(catalogId));
        }

        public static ProductList SearchProductList(string searchString)
        {
            return DataPortal.Fetch<ProductList>(new SingleCriteria<ProductList, string>(searchString));
        }

        public static ProductInfo GetProductInfo(int productId)
        {
            ProductList productList = DataPortal.Fetch<ProductList>(new SingleCriteria<ProductList, int>(productId));
            ProductInfo productInfo = null;

            if (productList.Count > 0)
            {
                productInfo = productList.Items[0];
            }
            return productInfo;
        }
       
        private ProductList()
        {
            // require use of factory methods
        }

        #endregion

        #region Data Access

        [Serializable()]
        private class CatalogCriteria
        {
            private int _catalogId;

            public int CatalogId
            {
                get
                {
                    return _catalogId;
                }
                set
                {
                    _catalogId = value;
                }
            }

            public CatalogCriteria(int catalogId)
            {
                _catalogId = catalogId;
            }
        }

        private void DataPortal_Fetch()
        {
            Database db = DatabaseFactory.CreateDatabase("SiteWorx");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_Products_GetProducts");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);

            try
            {
                using (var dr = new SafeDataReader(db.ExecuteReader(dbCommand)))
                {
                    RaiseListChangedEvents = false;
                    IsReadOnly = false;

                    while (dr.Read())
                    {
                          ProductInfo info = new ProductInfo(dr.GetInt32("ProductID"), dr.GetString("Title"), dr.GetString("Description"),
                                                             dr.GetString("ItemNumber"), dr.GetString("Dimensions"), dr.GetDecimal("UnitPrice"), 
                                                             dr.GetString("ImagePath"), dr.GetInt32("Position"), dr.GetGuid("CreatedBy"), 
                                                             dr.GetSmartDate("CreatedDate"), dr.GetGuid("LastUpdatedBy"), dr.GetSmartDate("LastUpdatedDate"));
                          this.Add(info);
                    }
                    IsReadOnly = true;
                    RaiseListChangedEvents = true;
                }
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }
        }

        private void DataPortal_Fetch(CatalogCriteria criteria)
        {
            Database db = DatabaseFactory.CreateDatabase("SiteWorx");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_Products_RetrieveProducts");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "ProductCatalogId", DbType.Int32, criteria.CatalogId);

            try
            {
                using (var dr = new SafeDataReader(db.ExecuteReader(dbCommand)))
                {
                    RaiseListChangedEvents = false;
                    IsReadOnly = false;

                    while (dr.Read())
                    {
                        ProductInfo info = new ProductInfo(dr.GetInt32("ProductID"), dr.GetString("Title"), dr.GetString("Description"),
                                                             dr.GetString("ItemNumber"), dr.GetString("Dimensions"), dr.GetDecimal("UnitPrice"), 
                                                             dr.GetString("ImagePath"), dr.GetInt32("Position"), dr.GetGuid("CreatedBy"), 
                                                             dr.GetSmartDate("CreatedDate"), dr.GetGuid("LastUpdatedBy"), dr.GetSmartDate("LastUpdatedDate"));
                        this.Add(info);
                    }
                    IsReadOnly = true;
                    RaiseListChangedEvents = true;
                }
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }
        }

        private void DataPortal_Fetch(SingleCriteria<ProductList, string> criteria)
        {
            Database db = DatabaseFactory.CreateDatabase("SiteWorx");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_Products_SearchProducts");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "SearchString", DbType.String, criteria.Value);

            try
            {
                using (var dr = new SafeDataReader(db.ExecuteReader(dbCommand)))
                {
                    RaiseListChangedEvents = false;
                    IsReadOnly = false;

                    while (dr.Read())
                    {
                        ProductInfo info = new ProductInfo(dr.GetInt32("ProductID"), dr.GetString("Title"), dr.GetString("Description"),
                                                             dr.GetString("ItemNumber"), dr.GetString("Dimensions"), dr.GetDecimal("UnitPrice"), 
                                                             dr.GetString("ImagePath"), dr.GetInt32("Position"), dr.GetGuid("CreatedBy"), 
                                                             dr.GetSmartDate("CreatedDate"), dr.GetGuid("LastUpdatedBy"), dr.GetSmartDate("LastUpdatedDate"));
                        this.Add(info);
                    }
                    IsReadOnly = true;
                    RaiseListChangedEvents = true;
                }
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }
        }

        private void DataPortal_Fetch(SingleCriteria<ProductList, int> criteria)
        {
            Database db = DatabaseFactory.CreateDatabase("SiteWorx");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_Products_GetProduct");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "ProductId", DbType.Int32, criteria.Value);

            try
            {
                using (var dr = new SafeDataReader(db.ExecuteReader(dbCommand)))
                {
                    RaiseListChangedEvents = false;
                    IsReadOnly = false;

                    while (dr.Read())
                    {
                        ProductInfo info = new ProductInfo(dr.GetInt32("ProductID"), dr.GetString("Title"), dr.GetString("Description"),
                                                             dr.GetString("ItemNumber"), dr.GetString("Dimensions"), dr.GetDecimal("UnitPrice"), 
                                                             dr.GetString("ImagePath"), dr.GetInt32("Position"), dr.GetGuid("CreatedBy"), 
                                                             dr.GetSmartDate("CreatedDate"), dr.GetGuid("LastUpdatedBy"), dr.GetSmartDate("LastUpdatedDate"));
                        this.Add(info);
                    }
                    IsReadOnly = true;
                    RaiseListChangedEvents = true;
                }
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }
        }

        #endregion

    }
}
